package com.imooc.article.service.impl;

import com.github.pagehelper.PageHelper;
import com.imooc.api.config.RabbitMQDelayConfig;
import com.imooc.api.service.BaseService;
import com.imooc.article.mapper.ArticleMapper;
import com.imooc.article.mapper.ArticleMapperCustom;
import com.imooc.article.service.ArticleService;
import com.imooc.enums.ArticleReviewLevel;
import com.imooc.enums.ArticleReviewStatus;
import com.imooc.enums.YesOrNo;
import com.imooc.exception.GraceException;
import com.imooc.grance.result.ResponseStatusEnum;
import com.imooc.pojo.Article;
import com.imooc.pojo.bo.NewArticleBO;
import com.imooc.pojo.eo.ArticleEO;
import com.imooc.utils.PagedGridResult;
import com.imooc.utils.extend.AliTextReviewUtils;
import com.mongodb.client.gridfs.GridFSBucket;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.n3r.idworker.Sid;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;

@Service
public class ArticleServiceImpl extends BaseService implements ArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private ArticleMapperCustom articleMapperCustom;
    @Autowired
    private AliTextReviewUtils aliTextReviewUtils;
    @Autowired
    public GridFSBucket gridFSBucket;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ElasticsearchTemplate esTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(NewArticleBO newArticleBO) {
        Article article = new Article();
        String id = sid.nextShort();
        article.setId(id);
        article.setIsDelete(YesOrNo.NO.type);
        article.setArticleStatus(ArticleReviewStatus.REVIEWING.type);
        article.setReadCounts(0);
        article.setCommentCounts(0);
        article.setCreateTime(new Date());
        article.setUpdateTime(new Date());
        BeanUtils.copyProperties(newArticleBO, article);
        if (newArticleBO.getIsAppoint().equals(YesOrNo.NO.type)) {
            article.setPublishTime(new Date());
            //如果文章是定时发布，则使用MQ的定时消息
        }else if (newArticleBO.getIsAppoint().equals(YesOrNo.YES.type)){
            article.setPublishTime(newArticleBO.getPublishTime());
            Date startDate = newArticleBO.getPublishTime();
            Date endDate = new Date();
            int delayTime = (int) (endDate.getTime() - startDate.getTime());
            //方便测试写死一个时间   10s
            int exampleTime = 10 * 1000;
            MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    message.getMessageProperties().setDelay(exampleTime);
                    return message;
                }
            };
          rabbitTemplate.convertAndSend(RabbitMQDelayConfig.EXCHANGE_DELAY,
                              "delay.publisharticle",
                              id,
                              messagePostProcessor);
            System.out.println("生产者发送消息的时间"+new Date());
        }
        int result = articleMapper.insert(article);
        if (result != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_CREATE_ERROR);
        }
        //调用阿里的内容审核Api
//        String reviewTextResult = aliTextReviewUtils.reviewTextContent(newArticleBO.getContent());
        //机审结束没接下里要人工审核
        String reviewTextResult = ArticleReviewLevel.REVIEW.type;
        if (reviewTextResult.equalsIgnoreCase(ArticleReviewLevel.PASS.type)) {
            //修改文章的状态为审核通过
            updatearticleStatus(id, ArticleReviewStatus.SUCCESS.type);
        } else if (reviewTextResult.equalsIgnoreCase(ArticleReviewLevel.REVIEW.type)) {
            //修改文章的状态为建议人工审核
            updatearticleStatus(id, ArticleReviewStatus.WAITING_MANUAL.type);
        }else if (reviewTextResult.equalsIgnoreCase(ArticleReviewLevel.BLOCK.type)) {
            //修改文章的状态为审核不通过
            updatearticleStatus(id, ArticleReviewStatus.FAILED.type);
        }
    }

    @Override
    public void updateOppiontToPublic() {
        articleMapperCustom.updateOppiontToPublic();
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public PagedGridResult articleList(String userId,
                                       Integer status,
                                       Date startDate,
                                       Date endDate,
                                       Integer page,
                                       Integer pageSize,
                                       String keyword) {
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isBlank(userId)) {
            GraceException.display(ResponseStatusEnum.ARTICLE_QUERY_PARAMS_ERROR);
        }
        criteria.andEqualTo("publishUserId", userId);
        if (ArticleReviewStatus.isArticleStatusValid(status)) {
            criteria.andEqualTo("articleStatus", status);
        }
        if (status != null && status == 12) {
            criteria.andEqualTo("articleStatus", ArticleReviewStatus.REVIEWING.type)
                    .orEqualTo("articleStatus",ArticleReviewStatus.WAITING_MANUAL.type);
        }
        if (startDate != null) {
            criteria.andGreaterThanOrEqualTo("publishTime", startDate);
        }
        if (endDate != null) {
            criteria.andGreaterThanOrEqualTo("publishTime", startDate);
        }
        if (StringUtils.isNotBlank(keyword)) {
            criteria.andLike("title", "%" + keyword + "%");
        }
        criteria.andEqualTo("isDelete", YesOrNo.NO.type);
        PageHelper.startPage(page, pageSize);
        List<Article> articles = articleMapper.selectByExample(example);
        PagedGridResult pagedGridResult = pagedResultSettings(articles, page);
        return pagedGridResult;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void updatearticleStatus(String articleId, Integer status) {
        Example example = new Example(Article.class);
        Example.Criteria criteria= example.createCriteria();
        criteria.andEqualTo("id", articleId);
        Article article = new Article();
        article.setArticleStatus(status);
        int result = articleMapper.updateByExampleSelective(article, example);
        if (result != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_CREATE_ERROR);
        }
        //如果审核通过就把文章后存入   elasticsearch中
        if (status.equals(ArticleReviewStatus.SUCCESS.type)) {
            ArticleEO articleEO = new ArticleEO();
            Article article1 = articleMapper.selectByPrimaryKey(article);
            BeanUtils.copyProperties(article1,articleEO);
            IndexQuery indexQuery = new IndexQueryBuilder()
                    .withObject(articleEO)
                    .withIndexName("articles")
                    .build();
            esTemplate.index(indexQuery);
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public PagedGridResult findAll(Integer status, Integer page, Integer pageSize) {
        System.out.println("status: "+status);
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        if (ArticleReviewStatus.isArticleStatusValid(status)) {
            criteria.andEqualTo("articleStatus", status);
        }

        if (status != null && status == 12) {
            criteria.andEqualTo("articleStatus", ArticleReviewStatus.WAITING_MANUAL.type).
            orEqualTo("articleStatus", ArticleReviewStatus.REVIEWING.type);
        }
        criteria.andEqualTo("isDelete", YesOrNo.NO.type);
        example.orderBy("createTime").desc();
        PageHelper.startPage(page, pageSize);
        List<Article> articles = articleMapper.selectByExample(example);

        PagedGridResult pagedGridResult = pagedResultSettings(articles, page);
        return pagedGridResult;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void deleteArticle(String articleId, String userId) {
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", articleId);
        criteria.andEqualTo("publishUserId", userId);
        Article article = new Article();
        article.setIsDelete(YesOrNo.YES.type);
        int result = articleMapper.updateByExampleSelective(article, example);
        if (result != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_DELETE_ERROR);
        }
        //用户删除文章之后，也把es中的数据删除
        esTemplate.delete(ArticleEO.class, articleId);
    }
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void withdrawArticle(String articleId, String userId) {
        if (StringUtils.isBlank(articleId) || StringUtils.isBlank(userId)) {
            GraceException.display(ResponseStatusEnum.ARTICLE_DELETE_ERROR);
        }
        Article article = new Article();
        article.setArticleStatus(ArticleReviewStatus.WITHDRAW.type);
        Example example = new Example(Article.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", articleId);
        criteria.andEqualTo("publishUserId", userId);
        int result = articleMapper.updateByExampleSelective(article, example);
        if (result != 1) {
            GraceException.display(ResponseStatusEnum.ARTICLE_WITHDRAW_ERROR);
        }
        //用户撤回文章之后，也把es中的数据删除
        esTemplate.delete(ArticleEO.class, articleId);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateArticleToGridFs(String articleId, String mongoFileId) {
        Article article = new Article();
        article.setId(articleId);
        article.setMongoFileId(mongoFileId);
        int result = articleMapper.updateByPrimaryKeySelective(article);
        if (result != 1) {
            GraceException.display(ResponseStatusEnum.FILE_UPLOAD_FAILD);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateArticleToPublish(String articleId) {
        Article article = new Article();
        article.setId(articleId);
        article.setPublishTime(new Date());
        article.setIsAppoint(YesOrNo.NO.type);
        articleMapper.updateByPrimaryKeySelective(article);
    }
}


